import { BaseSession } from './base'
import {fromAny, StringValue, toAny} from '../proto'
export class TextToSpeechSession extends BaseSession {
    private onStartListener: (utteranceId: string) => void
    private onStopListener: (utteranceId: string) => void
    private onDoneListener: (utteranceId: string) => void
    private onErrorListener: (utteranceId: string) => void
    private utteranceIds: Set<string>
    constructor(render: HTMLElement) {
        super('TextToSpeech', render)
        this.utteranceIds = new Set()
    }
    onCreate(sessionId: number, futureId: number, ...argv) {
        super.onCreate(sessionId, futureId, ...argv);
        this.sendCallback(argv[0]).then(() => {})
    }
    onReceive(name: String, sessionId: number, futureId: number, ...argv) {
        switch (name) {
            case 'speak':
                return this.speak(...argv)
            case 'stop':
                return this.stop()
            case 'setOnStartListener':
                return this.setOnStartListener(...argv)
            case 'setOnStopListener':
                return this.setOnStopListener(...argv)
            case 'setOnDoneListener':
                return this.setOnDoneListener(...argv)
            case 'setOnErrorListener':
                return this.setOnErrorListener(...argv)
        }
        super.onReceive(name, sessionId, futureId, ...argv);
    }
    speak(...argv) {
        if (!argv || argv.length < 1)
            throw new Error("Missing param `text` from the server calling this `speak` method.")
        const text = fromAny(argv[0], StringValue)
        const utteranceId: string = (argv && argv.length > 1) ? fromAny(argv[1], StringValue) : ''
        const msg = new SpeechSynthesisUtterance()
        msg.lang = "zh-CN"
        msg.volume = 0.8
        msg.rate = 1.5
        msg.pitch = 0.8
        msg.text = text
        msg.onstart = () => {
            if (this.onStartListener)
                this.onStartListener(utteranceId)
            this.utteranceIds.add(utteranceId)
        }
        msg.onend = () => {
            if (this.onDoneListener)
                this.onDoneListener(utteranceId)
            this.utteranceIds.delete(utteranceId)
        }
        msg.onerror = () => {
            if (this.onErrorListener)
                this.onErrorListener(utteranceId)
            this.utteranceIds.delete(utteranceId)
        }
        window.speechSynthesis.speak(msg)
    }
    private stop() {
        this.utteranceIds.forEach(u => {
            if (this.onStopListener)
                this.onStopListener(u)
        })
        window.speechSynthesis.cancel()
        this.utteranceIds.clear()
    }
    private setOnStartListener(...argv) {
        this.onStartListener = (utteranceId) => this.sendCallback(argv[0], toAny(utteranceId, StringValue))
    }
    private setOnStopListener(...argv) {
        this.onStopListener = (utteranceId) => this.sendCallback(argv[0], toAny(utteranceId, StringValue))
    }
    private setOnDoneListener(...argv) {
        this.onDoneListener = (utteranceId) => this.sendCallback(argv[0], toAny(utteranceId, StringValue))
    }
    private setOnErrorListener(...argv) {
        this.onErrorListener = (utteranceId) => this.sendCallback(argv[0], toAny(utteranceId, StringValue))
    }
}